/**
 * @File Name: Log.cpp
 * @brief  
 * @Author : LiWanglin email:lwl510ll@163.com
 * @Version : 1.0
 * @Creat Date : 2023-12-03
 * 
 * @copyright Copyright (c) 2023 LiWanglin
 */

#include "log.h"
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>

/*设置输出前景色*/
#define PRINT_FONT_BLA  printf("\033[30m"); //黑色
#define PRINT_FONT_RED  printf("\033[31m"); //红色
#define PRINT_FONT_GRE  printf("\033[32m"); //绿色
#define PRINT_FONT_YEL  printf("\033[33m"); //黄色
#define PRINT_FONT_BLU  printf("\033[34m"); //蓝色
#define PRINT_FONT_PUR  printf("\033[35m"); //紫色
#define PRINT_FONT_CYA  printf("\033[36m"); //青色
#define PRINT_FONT_WHI  printf("\033[37m"); //白色
/*设置输出背景色*/ 
#define PRINT_BACK_BLA  printf("\033[40m"); //黑色
#define PRINT_BACK_RED  printf("\033[41m"); //红色
#define PRINT_BACK_GRE  printf("\033[42m"); //绿色
#define PRINT_BACK_YEL  printf("\033[43m"); //黄色
#define PRINT_BACK_BLU  printf("\033[44m"); //蓝色
#define PRINT_BACK_PUR  printf("\033[45m"); //紫色
#define PRINT_BACK_CYA  printf("\033[46m"); //青色
#define PRINT_BACK_WHI  printf("\033[47m"); //白色
/*输出属性设置*/
#define PRINT_ATTR_REC  printf("\033[0m");  //重新设置属性到缺省设置 
#define PRINT_ATTR_BOL  printf("\033[1m");  //设置粗体 
#define PRINT_ATTR_LIG  printf("\033[2m");  //设置一半亮度(模拟彩色显示器的颜色) 
#define PRINT_ATTR_LIN  printf("\033[4m");  //设置下划线(模拟彩色显示器的颜色) 
#define PRINT_ATTR_GLI  printf("\033[5m");  //设置闪烁 
#define PRINT_ATTR_REV  printf("\033[7m");  //设置反向图象 
#define PRINT_ATTR_THI  printf("\033[22m"); //设置一般密度 
#define PRINT_ATTR_ULIN  printf("\033[24m");//关闭下划线 
#define PRINT_ATTR_UGLI  printf("\033[25m");//关闭闪烁 
#define PRINT_ATTR_UREV  printf("\033[27m");//关闭反向图象

static Log *log = nullptr;

Log *Log::get_instance() 
{
    if(nullptr == log) {
        log = new Log();
    }

    return log;
}

Log::Log()
{
    save_path = "./lw_app.log";
    file_size = 1024;
    back_count = 2;
    log_fd = -1;
    start_flag = false;
    print_flag = 1;
    write_file_flag = false;
}

Log::Log(const char *path, int32_t size, int32_t count)
{
    save_path = path;
    file_size = size;
    back_count = count;
    log_fd = -1;
    start_flag = false;
    print_flag = 1;
    write_file_flag = false;
}

Log::~Log()
{

}

/**
 * @brief  
 * @return CMResult: 
 */
CMResult Log::init()
{
    CMResult ret = CM_OK;

    if((save_path != nullptr) && (write_file_flag == true)) {
        /* 打开文件 */
        log_fd = open(save_path, O_CREAT|O_RDWR, 0666);
        if(log_fd < 0) {
            ret = CM_OPEN_FILE_ERROR;
        }
    } else if (write_file_flag == false){
        ret = CM_OK;
    } else {
        ret = CM_OPEN_FILE_ERROR;
    }

    if(ret == CM_OK || log_fd > 0) {
        /* 清空文件内容 */
        ftruncate(log_fd, 0);
        lseek(log_fd, 0, SEEK_SET);
    }

    return ret;
}

/**
 * @brief  
 * @return CMResult: 
 */
CMResult Log::uninit()
{
    if(log_fd > 0) {
        close(log_fd);
    }

    return CM_OK;
}

CMResult Log::start()
{
    start_flag = true;
    return CM_OK;
}

CMResult Log::stop()
{
    start_flag = false;
    return CM_OK;
}

CMResult Log::set(int type, void *arg)
{
    switch (type)
    {
        case LW_SET_LOG_PATH:
            save_path = (char *)arg;
            break;
        case LW_SET_ENABLE_FILE_WRITE:
            write_file_flag = *(bool *)arg;
            break;
        default:
            break;
    }

    return CM_OK;
}

CMResult Log::out(LogLevel level, const char *file, const char *func, int line, const char *format, ...)
{
    if(start_flag) {
        char temp_buf[1040] = { 0 };
        char buf[1024] = { 0 };
        va_list ap;
        va_start(ap, format);
        vsprintf(buf, format, ap);
        va_end(ap);
        switch (level)
        {
            case LOG_LEVEL_DEBUG:
                PRINT_FONT_WHI
                sprintf(temp_buf, "[%s:%d] %s DEBUG: %s\n", file, line, func, buf);
                break;
            case LOG_LEVEL_INFO:
                sprintf(temp_buf, "[%s:%d] %s INFO: %s\n", file, line, func, buf);
                break;
            case LOG_LEVEL_WARN:
                PRINT_FONT_BLU 
                sprintf(temp_buf, "[%s:%d] %s WARN: %s\n", file, line, func, buf);
                break;
            case LOG_LEVEL_FATAL:
                PRINT_FONT_RED
                sprintf(temp_buf, "[%s:%d] %s FATAL: %s\n", file, line, func, buf);
                break;
            case LOG_LEVEL_ERROR:
                PRINT_FONT_RED
                sprintf(temp_buf, "[%s:%d] %s ERROR: %s\n", file, line, func, buf);
                break;
            default:
                break;
        }

        if(print_flag) {
            printf("%s", temp_buf);
        }
        PRINT_ATTR_REC

        if(log_fd > 0) {
            write(log_fd, temp_buf, sizeof(temp_buf));
        }
    }

    return CM_OK;
}